/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    adc.c
  * @brief   本文件提供 ADC 实例配置相关代码
  * @details 包含ADC初始化、DMA配置、ADC中断处理以及采样数据处理功能
  * @author  STMicroelectronics
  * @date    2025
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * 保留所有权利。
  *
  * 此软件依据位于该软件组件根目录下的 LICENSE 文件中的条款进行许可。
  * 如果该软件没有附带 LICENSE 文件，则按"原样"提供。
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "adc.h"  /* ADC头文件 */

/* USER CODE BEGIN 0 */
/**
 * @file    adc.c 用户代码部分
 * @brief   ADC采样数据处理和相关变量定义
 */
#include "KEY.h"  /* 按键相关头文件 */

/**
 * @var    current_sum
 * @brief  电流采样值总和
 * @details 用于累积多次ADC电流采样值
 */
uint32_t current_sum = 0;

/**
 * @var    mcu_temp_sum
 * @brief  MCU温度采样值总和
 * @details 用于累积多次ADC的MCU温度传感器采样值
 */
uint32_t mcu_temp_sum = 0;

/**
 * @var    led1_temp_sum
 * @brief  LED温度采样值总和
 * @details 用于累积多次ADC的LED1温度传感器采样值
 */
uint32_t led1_temp_sum = 0;

/**
 * @var    led2_temp_sum
 * @brief  LED温度采样值总和
 * @details 用于累积多次ADC的LED2温度传感器采样值
 */
uint32_t led2_temp_sum = 0;

/**
 * @var    led3_temp_sum
 * @brief  LED温度采样值总和
 * @details 用于累积多次ADC的LED3温度传感器采样值
 */
uint32_t led3_temp_sum = 0;

/**
 * @var    brightness_sum
 * @brief  亮度采样值总和
 * @details 用于累积多次ADC的亮度传感器采样值
 */
uint32_t brightness_sum = 0;

/**
 * @var    infrared_sum
 * @brief  红外采样值总和
 * @details 用于累积多次ADC的红外传感器采样值
 */
uint32_t infrared_sum = 0;

/**
 * @var    adc_count
 * @brief  采样次数计数器
 * @details 记录ADC采样的次数
 */
uint16_t adc_count = 0;

/**
 * @var    current_avg
 * @brief  电流采样平均值
 * @details 电流采样的平均值，通过current_sum除以adc_count计算得到
 */
float current_avg = 0;

/**
 * @var    mcu_temp_avg
 * @brief  MCU温度采样平均值
 * @details MCU温度采样的平均值，通过mcu_temp_sum除以adc_count计算得到
 */
float mcu_temp_avg = 0;

/**
 * @var    led1_temp_avg
 * @brief  LED温度采样平均值
 * @details LED1温度采样的平均值，通过led1_temp_sum除以adc_count计算得到
 */
float led1_temp_avg = 0;

/**
 * @var    led2_temp_avg
 * @brief  LED温度采样平均值
 * @details LED2温度采样的平均值，通过led2_temp_sum除以adc_count计算得到
 */
float led2_temp_avg = 0;

/**
 * @var    led3_temp_avg
 * @brief  LED温度采样平均值
 * @details LED3温度采样的平均值，通过led3_temp_sum除以adc_count计算得到
 */
float led3_temp_avg = 0;

/**
 * @var    brightness_avg
 * @brief  亮度采样平均值
 * @details 亮度采样的平均值，通过brightness_sum除以adc_count计算得到
 */
float brightness_avg = 0;

/**
 * @var    infrared_avg
 * @brief  红外采样平均值
 * @details 红外采样的平均值，通过infrared_sum除以adc_count计算得到
 */
float infrared_avg = 0;
/* USER CODE END 0 */

/**
 * @var    hadc
 * @brief  ADC句柄
 * @details 存储ADC配置参数和状态信息
 */
ADC_HandleTypeDef hadc;

/**
 * @var    hdma_adc
 * @brief  ADC DMA句柄
 * @details 存储ADC的DMA配置参数和状态信息
 */
DMA_HandleTypeDef hdma_adc;

/**
 * @brief   ADC初始化函数
 * @details 配置ADC的时钟、分辨率、数据对齐方式和转换模式等参数
 * @param   无
 * @retval  无
 */
void MX_ADC_Init(void)
{
  /* USER CODE BEGIN ADC_Init 0 */

  /* USER CODE END ADC_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC_Init 1 */

  /* USER CODE END ADC_Init 1 */

  /** 配置ADC的全局特性（时钟、分辨率、数据对齐和转换数量）
  */
  hadc.Instance = ADC1;                                    // ADC实例为ADC1
  hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;     // 时钟预分频为PCLK/4
  hadc.Init.Resolution = ADC_RESOLUTION_12B;               // 分辨率为12位
  hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;               // 数据右对齐
  hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;     // 扫描方向为正向
  hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV;               // 转换结束标志为序列转换结束
  hadc.Init.LowPowerAutoWait = DISABLE;                    // 禁用低功耗自动等待
  hadc.Init.LowPowerAutoPowerOff = DISABLE;                // 禁用低功耗自动断电
  hadc.Init.ContinuousConvMode = ENABLE;                   // 启用连续转换模式
  hadc.Init.DiscontinuousConvMode = DISABLE;               // 禁用间断转换模式
  hadc.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_TRGO;  // 外部触发源为TIM3触发输出
  hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;  // 触发边沿为上升沿
  hadc.Init.DMAContinuousRequests = ENABLE;                // 启用DMA连续请求
  hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;              // 数据溢出时保留旧数据
  if (HAL_ADC_Init(&hadc) != HAL_OK)                       // 初始化ADC
  {
    Error_Handler();                                       // 初始化失败时调用错误处理函数
  }

  /** 配置要转换的ADC常规通道
  */
  sConfig.Channel = ADC_CHANNEL_3;                         // 通道为ADC通道3
  sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;                  // 转换顺序为通道编号顺序
  sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;        // 采样时间为55.5个周期
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)    // 配置ADC通道
  {
    Error_Handler();                                       // 配置失败时调用错误处理函数
  }

  /** 配置要转换的ADC常规通道
  */
  sConfig.Channel = ADC_CHANNEL_9;                         // 通道为ADC通道9
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)    // 配置ADC通道
  {
    Error_Handler();                                       // 配置失败时调用错误处理函数
  }
  /* USER CODE BEGIN ADC_Init 2 */

  /* USER CODE END ADC_Init 2 */

}

/**
 * @brief   ADC MSP初始化函数
 * @details 配置ADC的底层硬件资源，包括时钟、GPIO和DMA
 * @param   adcHandle: 指向ADC_HandleTypeDef结构体的指针，包含ADC配置信息
 * @retval  无
 */
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(adcHandle->Instance==ADC1)  // 如果是ADC1实例
  {
  /* USER CODE BEGIN ADC1_MspInit 0 */

  /* USER CODE END ADC1_MspInit 0 */
    /* ADC1时钟使能 */
    __HAL_RCC_ADC1_CLK_ENABLE();

    /* GPIO时钟使能 */
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**ADC GPIO配置
    PA3     ------> ADC_IN3
    PB1     ------> ADC_IN9
    */
    GPIO_InitStruct.Pin = Mcu_Tem_Pin;                    // MCU温度传感器引脚
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;              // 模拟模式
    GPIO_InitStruct.Pull = GPIO_NOPULL;                   // 无上下拉
    HAL_GPIO_Init(Mcu_Tem_GPIO_Port, &GPIO_InitStruct);   // 初始化GPIO

    GPIO_InitStruct.Pin = LED3_tem_Pin;                   // LED3温度传感器引脚
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;              // 模拟模式
    GPIO_InitStruct.Pull = GPIO_NOPULL;                   // 无上下拉
    HAL_GPIO_Init(LED3_tem_GPIO_Port, &GPIO_InitStruct);  // 初始化GPIO

    /* ADC1 DMA初始化 */
    /* ADC Init */
    hdma_adc.Instance = DMA1_Channel1;                    // DMA实例为DMA1通道1
    hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY;       // 传输方向为外设到内存
    hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE;           // 禁用外设地址增量
    hdma_adc.Init.MemInc = DMA_MINC_ENABLE;               // 启用内存地址增量
    hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;  // 外设数据对齐为半字
    hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;     // 内存数据对齐为半字
    hdma_adc.Init.Mode = DMA_CIRCULAR;                    // 循环模式
    hdma_adc.Init.Priority = DMA_PRIORITY_LOW;            // 优先级为低
    if (HAL_DMA_Init(&hdma_adc) != HAL_OK)                // 初始化DMA
    {
      Error_Handler();                                    // 初始化失败时调用错误处理函数
    }

    /* 将DMA链接到ADC */
    __HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc);

    /* ADC1中断初始化 */
    HAL_NVIC_SetPriority(ADC1_IRQn, 0, 0);                 // 设置中断优先级
    HAL_NVIC_EnableIRQ(ADC1_IRQn);                         // 使能中断
  /* USER CODE BEGIN ADC1_MspInit 1 */

  /* USER CODE END ADC1_MspInit 1 */
  }
}

/**
 * @brief   ADC MSP解初始化函数
 * @details 释放ADC的底层硬件资源
 * @param   adcHandle: 指向ADC_HandleTypeDef结构体的指针，包含ADC配置信息
 * @retval  无
 */
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
{
  if(adcHandle->Instance==ADC1)  // 如果是ADC1实例
  {
  /* USER CODE BEGIN ADC1_MspDeInit 0 */

  /* USER CODE END ADC1_MspDeInit 0 */
    /* 禁用外设时钟 */
    __HAL_RCC_ADC1_CLK_DISABLE();

    /**ADC GPIO配置
    PA3     ------> ADC_IN3
    PB1     ------> ADC_IN9
    */
    HAL_GPIO_DeInit(Mcu_Tem_GPIO_Port, Mcu_Tem_Pin);      // 解初始化GPIO

    HAL_GPIO_DeInit(LED3_tem_GPIO_Port, LED3_tem_Pin);     // 解初始化GPIO

    /* ADC1 DMA解初始化 */
    HAL_DMA_DeInit(adcHandle->DMA_Handle);                 // 解初始化DMA

    /* ADC1中断解初始化 */
    HAL_NVIC_DisableIRQ(ADC1_IRQn);                        // 禁用中断
  /* USER CODE BEGIN ADC1_MspDeInit 1 */

  /* USER CODE END ADC1_MspDeInit 1 */
  }
}

/* USER CODE BEGIN 1 */
/**
 * @brief   ADC转换完成回调函数
 * @details 在ADC完成一次转换序列后，此函数会被调用。它会累加采样值，
 *          当采样次数达到1000次时，计算平均值并进行相关处理。
 * @param   hadc: 指向ADC_HandleTypeDef结构体的指针，包含ADC配置信息
 * @retval  无
 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
//    extern uint16_t ADC_Value[5];
//    // 电流采样值
//    uint16_t current = ADC_Value[0];
//    // MCU温度采样值
//    uint16_t mcu_temperature = ADC_Value[1];
//    // LED温度采样值
//    uint16_t led1_temperature = ADC_Value[2];
//	  uint16_t led2_temperature = ADC_Value[2];
//	  uint16_t led3_temperature = ADC_Value[2];
//    
//    current_sum += current;
//    mcu_temp_sum += mcu_temperature;
//    led1_temp_sum += led1_temperature;
//  	led2_temp_sum += led2_temperature;
//  	led3_temp_sum += led3_temperature;
//    adc_count++;
//    if (adc_count >= 1000) {
//        // 计算平均值
//        current_avg = (float)current_sum / 1000;
//        mcu_temp_avg = (float)mcu_temp_sum / 1000;
//        led1_temp_avg = (float)led1_temp_sum / 1000;
//		  	led2_temp_avg = (float)led2_temp_sum / 1000;
//		  	led3_temp_avg = (float)led3_temp_sum / 1000;
//       
//        
//        float current_value = (current_avg + 20) * 0.806; // 电流转换
//        float mcu_temp_value = mcu_temp_avg ; // MCU温度转换
//        float led1_temp_value = led1_temp_avg ; // LED温度转换
//			  float led2_temp_value = led2_temp_avg ; // LED温度转换
//			  float led3_temp_value = led3_temp_avg ; // LED温度转换
//        if (current_value > 700) {
//          DeviceStatus.powerState = 0;
//        }
//        if (mcu_temp_value< 608) {//70度时电阻约为1.745,1.745/11.745*4095=608
//          DeviceStatus.powerState = 0;
//        }
//        if (led1_temp_value < 343) {//90度时电阻约为0.915,
//          DeviceStatus.powerState = 0;
//        }
//				if (led2_temp_value < 343) {//90度时电阻约为0.915,
//          DeviceStatus.powerState = 0;
//        }
//				if (led3_temp_value < 343) {//90度时电阻约为0.915,
//          DeviceStatus.powerState = 0;
//        }
//        // 打印平均值信息（注释状态）
//        // printf("Current average: %.2f\n", current_avg);
//        // printf("MCU temperature average: %.2f\n", mcu_temp_avg);
//        // printf("LED temperature average: %.2f\n", led_temp_avg);
//        // printf("Brightness average: %.2f\n", brightness_avg);
//        // printf("Infrared average: %.2f\n", infrared_avg);
//        // 重置累加值和计数器
//        current_sum = 0;
//        mcu_temp_sum = 0;
//        led1_temp_sum = 0;
//				led2_temp_sum = 0;
//				led3_temp_sum = 0;
//        adc_count = 0;
//    }
}
/* USER CODE END 1 */
